#include <mboot.h>
#include <common.h>
#include <vmm.h>
#include <elf.h>
#include <thread.h>
#include <process.h>
#include <gdt.h>
#include <idt.h>

elf_t kernel_elf;
mboot_info *kernel_multiboot;

int kernel_main(void *arg);
int userspace_thread(void *arg);
int main(mboot_info *multiboot_info, unsigned int initial_stack)
{
	irq_fired = 0;
	kernel_multiboot = multiboot_info;
	init_gdt();
	init_idt();
	init_timer(20);
	init_video();
	init_pmm(multiboot_info->mem_upper);

	init_vmm();
	kernel_elf = elf_from_multiboot(multiboot_info);

	asm("sti");

	init_syscalls();
	init_scheduler(init_threading(initial_stack));

	extern kernel_stack;
	global_tss.esp0 = (unsigned int)&kernel_stack + 0x1FF0;
	
	if(multiboot_info->mods_count == 0)
		panic("No init!");
	
	unsigned int elf_start = *((unsigned int*)(multiboot_info->mods_addr + 0xC0000000));

	unsigned int addr = elf_load((unsigned char *)(elf_start + 0xC0000000));

	thread *t = (thread *)create_thread(&kernel_main, (void *)addr, 0x2000);
	thread_is_ready(t);

	//This thread is from now on the idle thread.
	current_thread->state = TH_ZOMBIE;
	for(;;)
	{
		asm("hlt");
	}
}

int kernel_main(void *arg)
{
	unsigned int p;
	asm volatile ("int $0xFF" : "=a" (p) : "0" (0x100));	//fork()
	if(p == 0)
	{
		printf("Is child");
		mboot_mod *modules = (mboot_mod *)((unsigned int)kernel_multiboot->mods_addr + 0xC0000000);
		asm volatile ("int $0xFF" : : "a" (0x108), "b" (modules[0].mod_start + 0xC0000000), "c" (modules[1].mod_start + 0xC0000000)); //"exec()"
		for(;;);
	}
	
/*	asm volatile ("int $0xFF" : "=a" (i) : "0" (0x103));
	printf("\nPID:%x\n",i);
	asm volatile ("int $0xFF" : "=a" (i) : "0" (0x104));
	printf("\nPPID:%x\n",i);
	asm volatile ("int $0xFF" : "=a" (buffer) : "0" (0x401));

	registers v86r;
	v86r.eax = 0x4f00;
	v86r.v86es = 0x0;
	v86r.edi = buffer;
	
	asm volatile ("int $0xFF" : "=a" (i) : "0" (0x400), "b" (0x10), "c" (&v86r));
	unsigned volatile char *vbe = buffer;
	printf("Returned %x!",i);
	printf("\neax:%x",v86r.eax);
	printf(vbe);
*/

//	asm volatile ("int $0xFF" : : "a" (0x101));
	for(;;)
	asm volatile ("int $0xFF" : : "a" (0x106));
}
